package com.gitee.sparta.core.cluster.strategy;

import com.gitee.sparta.common.helpers.JsonHelper;
import com.gitee.sparta.core.bean.cluster.ClusterProtocol;
import com.gitee.sparta.core.bean.cluster.ServerBean;
import com.gitee.sparta.core.cluster.AbstractClusterFollower;
import com.gitee.sparta.core.cluster.AbstractClusterLeader;
import com.gitee.sparta.core.cluster.balance.LoadBalance;
import com.gitee.sparta.core.property.SpartaCoreProperties;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;

import java.nio.channels.SocketChannel;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 *      询问是否是 leader
 * </p>
 *
 * @author zyred
 * @since v 0.0.2
 */
@Slf4j
public class SwitchoverLeaderStrategy extends Strategy {

    private AbstractClusterFollower follower;

    public SwitchoverLeaderStrategy(RedissonClient client,
                                    LoadBalance loadBalance,
                                    SpartaCoreProperties properties,
                                    AbstractClusterFollower follower) {
        super(client, loadBalance, properties);
        this.follower = follower;
    }

    @Override
    public void handle(ChannelHandlerContext ctx, SocketChannel sc, ClusterProtocol cp) {
        RMap<Integer, ServerBean> serverTable = this.client.getMap(this.properties.getServerTable());
        ServerBean candidateLeader = serverTable.values().stream()
                .filter(a -> a.isLeader() && a.isCandidate()).findFirst().orElse(null);

        if (Objects.isNull(candidateLeader)) {
            log.error("[Sparta] Not found candidate ..., server table: {}",
                    JsonHelper.getJsonString(serverTable));
            return;
        }

        try {
            this.follower.buildFollower(candidateLeader.getServerIp(), candidateLeader.getServerPort());
        } catch (Exception e) {
            log.error("[Sparta] Connection new leader fail, ex :{}", e.getMessage(), e);
            return;
        }

        log.info("[Sparta] Connection new leader success ....., ip: {}, port: {}",
                candidateLeader.getServerIp(), candidateLeader.getServerPort());
    }
}
